package com.crazydream.wechat.security.service;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.util.AntPathRequestMatcher;
import org.springframework.security.web.util.RegexRequestMatcher;
import org.springframework.security.web.util.RequestMatcher;

import com.crazydream.wechat.system.model.Resource;
import com.crazydream.wechat.system.model.Role;
import com.crazydream.wechat.system.service.ResourceService;
import com.crazydream.wechat.system.service.RoleService;

/**
 * 初始化时加载角色资源关联数据
 * 
 * @author shadow
 * @email 124010356@qq.com
 * @create 2012.04.28
 */
public class SecurityMetadataSourceExtendImpl implements
		SecurityMetadataSourceExtend {

	private boolean expire = false; // 过期标识

	private RoleService roleService; // 角色服务类

	private ResourceService resourceService; // 资源服务类

	private RequestMatcher requestMatcher; // 匹配规则

	private String matcher; // 规则标识

	private Map<String, Collection<ConfigAttribute>> kv = new HashMap<String, Collection<ConfigAttribute>>(); // 资源集合

	public RoleService getRoleService() {
		return roleService;
	}

	public void setRoleService(RoleService roleService) {
		this.roleService = roleService;
	}

	public ResourceService getResourceService() {
		return resourceService;
	}

	public void setResourceService(ResourceService resourceService) {
		this.resourceService = resourceService;
	}

	public boolean supports(Class<?> clazz) {
		return true;
	}

	// 初始化方法时候从数据库中读取资源
	// @PostConstruct
	public void init() {
		load();
	}

	public Collection<ConfigAttribute> getAllConfigAttributes() {
		Set<ConfigAttribute> attributes = new HashSet<ConfigAttribute>();
		for (Map.Entry<String, Collection<ConfigAttribute>> entry : kv
				.entrySet()) {
			attributes.addAll(entry.getValue());
		}
		return attributes;
	}

	public Collection<ConfigAttribute> getAttributes(Object object)
			throws IllegalArgumentException {
		HttpServletRequest request = ((FilterInvocation) object).getRequest();
		// System.out.println("requestUrl is " + request.getRequestURI());

		// 检测是否刷新了资源
		if (isExpire()) {
			// 清空原本资源
			kv.clear();
			expire = false;
		}

		// 如果资源Map为空的时候则重新加载一次
		if (null == kv || kv.isEmpty())
			load();

		// 检测请求与当前资源匹配的正确性
		Iterator<String> iterator = kv.keySet().iterator();
		while (iterator.hasNext()) {
			String uri = iterator.next();
			if (matcher.toLowerCase().equals("ant")) {
				requestMatcher = new AntPathRequestMatcher(uri);
			}
			if (matcher.toLowerCase().equals("regex")) {
				requestMatcher = new RegexRequestMatcher(uri, request
						.getMethod(), true);
			}
			if (requestMatcher.matches(request))
				return kv.get(uri);
		}
		return null;
	}

	/**
	 * 加载所有资源与权限的关系
	 */
	public void load() {
		List<Resource> resources = this.resourceService.findForAll();
		for (Resource resource : resources) {
			List<Role> roles = this.roleService.findByResourceId(resource
					.getId());
			kv.put(resource.getContent(), list2Collection(roles));
		}
	}

	/**
	 * 将List<Role>集合转换为框架需要的Collection<ConfigAttribute>集合
	 * 
	 * @param roles
	 * @return Collection<ConfigAttribute>
	 */
	private Collection<ConfigAttribute> list2Collection(List<Role> roles) {
		List<ConfigAttribute> list = new ArrayList<ConfigAttribute>();
		for (Role role : roles)
			list.add(new SecurityConfig(role.getName()));
		return list;
	}

	public void setMatcher(String matcher) {
		this.matcher = matcher;
	}

	public boolean isExpire() {
		return expire;
	}

	public void expireNow() {
		this.expire = true;
	}

}